﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace Gmantis.Controls.Chart
{
    public delegate void AxisRangeChangedEventHandler(object sender, AxisRangeChangedEventArgs e);
    public delegate void AnnoCreatedEventHandler(object sender, AnnoCreatedEventArgs e);

    public enum AxisScrollBarPosition
    {
        Auto,
        None
    }

    internal enum AxisView
    {
        None,
        Cartseian,
        Cartseian3D
    }

    [Flags]
    public enum AxisPosition
    {
        DisableLastLabelOverflow = 4,
        Far = 1,
        Inner = 8,
        Near = 0,
        OverData = 2
    }

    public enum AnnoPosition
    {
        Auto,
        Near,
        Far,
        None
    }

    public enum AnnoVisibility
    {
        HideOverlapped,
        ShowAll
    }

    public enum RadarLabelVisibility
    {
        First,
        All,
        None
    }

    public interface IAxisScrollBar
    {
        // Events
        event AxisRangeChangedEventHandler AxisRangeChanged;

        // Properties
        Axis Axis { get; set; }
        Thickness ScrollBarMargin { get; }
        AxisScrollBarPosition ScrollBarPosition { get; }
    }

    internal interface IAxisController
    {
        // Methods
        void AdjustAxis(IAxis ax, double delta);
    }

    public class Axis : AxisCanvas, INotifyPropertyChanged
    {
        // Fields
        private double _actualMax;
        private double _actualMin;
        private IAxisScrollBar _asb;
        private AxisType _axType;
        private Func<double, double> _dependentConverter;
        private bool _fixedType;
        private bool _isDependent;
        private bool? _isTime;
        private double _minScale;
        private const double _MinScale = 1E-05;
        private DispatcherTimer _timer;
        private double _tmpScale;
        private double _tmpValue;
        public static readonly DependencyProperty AnnoAngleProperty = DependencyProperty.Register("AnnoAngle", typeof(double), typeof(Axis), new PropertyMetadata(0.0, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty AnnoFormatProperty = DependencyProperty.Register("AnnoFormat", typeof(string), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnAnnoFormatChanged)));
        public static readonly DependencyProperty AnnoPositionProperty = DependencyProperty.Register("AnnoPosition", typeof(AnnoPosition), typeof(Axis), new PropertyMetadata(AnnoPosition.Auto, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty AnnoTemplateProperty = DependencyProperty.Register("AnnoTemplate", typeof(object), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty AnnoVisibilityProperty = DependencyProperty.Register("AnnoVisibilityProperty", typeof(AnnoVisibility), typeof(Axis), new PropertyMetadata(AnnoVisibility.HideOverlapped, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty AutoMaxProperty = DependencyProperty.Register("AutoMax", typeof(bool), typeof(Axis), new PropertyMetadata(true, new PropertyChangedCallback(Axis.OnAutoMaxChanged)));
        public static readonly DependencyProperty AutoMinProperty = DependencyProperty.Register("AutoMin", typeof(bool), typeof(Axis), new PropertyMetadata(true, new PropertyChangedCallback(Axis.OnAutoMinChanged)));
        public static readonly DependencyProperty AxisLineProperty = DependencyProperty.Register("AxisLine", typeof(Line), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        internal double Change;
        public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register("FontFamily", typeof(FontFamily), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(Axis), new PropertyMetadata(double.NaN, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty FontStretchProperty = DependencyProperty.Register("FontStretch", typeof(FontStretch), typeof(Axis), new PropertyMetadata(FontStretches.Normal, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty FontStyleProperty = DependencyProperty.Register("FontStyle", typeof(FontStyle), typeof(Axis), new PropertyMetadata(FontStyles.Normal, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty FontWeightProperty = DependencyProperty.Register("FontWeight", typeof(FontWeight), typeof(Axis), new PropertyMetadata(FontWeights.Normal, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register("Foreground", typeof(Brush), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        internal IAxis iax;
        public static readonly DependencyProperty IsTimeProperty = DependencyProperty.Register("IsTime", typeof(bool), typeof(Axis), new PropertyMetadata(false, new PropertyChangedCallback(Axis.OnIsTimeChanged)));
        internal bool IsValidFmt;
        internal bool IsValidTimeFmt;
        public static readonly DependencyProperty ItemsLabelBindingProperty = DependencyProperty.Register("ItemsLabelBinding", typeof(Binding), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty ItemsValueBindingProperty = DependencyProperty.Register("ItemsValueBinding", typeof(Binding), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty LogBaseProperty = DependencyProperty.Register("LogBase", typeof(double), typeof(Axis), new PropertyMetadata(double.NaN, new PropertyChangedCallback(Axis.OnLogBaseChanged)));
        public static readonly DependencyProperty MajorGridFillProperty = DependencyProperty.Register("MajorGridFill", typeof(Brush), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MajorGridStrokeDashesProperty = DependencyProperty.Register("MajorGridStrokeDashes", typeof(DoubleCollection), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MajorGridStrokeProperty = DependencyProperty.Register("MajorGridStroke", typeof(Brush), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MajorGridStrokeThicknessProperty = DependencyProperty.Register("MajorGridStrokeThickness", typeof(double), typeof(Axis), new PropertyMetadata(0.5, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MajorTickHeightProperty = DependencyProperty.Register("MajorTickHeight", typeof(double), typeof(Axis), new PropertyMetadata(3.0, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MajorTickOverlapProperty = DependencyProperty.Register("MajorTickOverlap", typeof(double), typeof(Axis), new PropertyMetadata(0.0, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MajorTickStrokeProperty = DependencyProperty.Register("MajorTickStroke", typeof(Brush), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MajorTickThicknessProperty = DependencyProperty.Register("MajorTickThickness", typeof(double), typeof(Axis), new PropertyMetadata(1.0, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MajorUnitProperty = DependencyProperty.Register("MajorUnit", typeof(double), typeof(Axis), new PropertyMetadata(double.NaN, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MaxProperty = DependencyProperty.Register("Max", typeof(double), typeof(Axis), new PropertyMetadata(double.NaN, new PropertyChangedCallback(Axis.OnMaxChanged)));
        public static readonly DependencyProperty MinorGridStrokeDashesProperty = DependencyProperty.Register("MinorGridStrokeDashes", typeof(DoubleCollection), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MinorGridStrokeProperty = DependencyProperty.Register("MinorGridStroke", typeof(Brush), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MinorGridStrokeThicknessProperty = DependencyProperty.Register("MinorGridStrokeThickness", typeof(double), typeof(Axis), new PropertyMetadata(0.25, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MinorTickHeightProperty = DependencyProperty.Register("MinorTickHeight", typeof(double), typeof(Axis), new PropertyMetadata(2.0, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MinorTickOverlapProperty = DependencyProperty.Register("MinorTickOverlap", typeof(double), typeof(Axis), new PropertyMetadata(0.0, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MinorTickStrokeProperty = DependencyProperty.Register("MinorTickStroke", typeof(Brush), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MinorTickThicknessProperty = DependencyProperty.Register("MinorTickThickness", typeof(double), typeof(Axis), new PropertyMetadata(1.0, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MinorUnitProperty = DependencyProperty.Register("MinorUnit", typeof(double), typeof(Axis), new PropertyMetadata(double.NaN, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty MinProperty = DependencyProperty.Register("Min", typeof(double), typeof(Axis), new PropertyMetadata(double.NaN, new PropertyChangedCallback(Axis.OnMinChanged)));
        private bool notify;
        public static readonly DependencyProperty OriginProperty = DependencyProperty.Register("Origin", typeof(double), typeof(Axis), new PropertyMetadata(double.NaN, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty PlotAreaIndexProperty = DependencyProperty.Register("PlotAreaIndex", typeof(int), typeof(Axis), new PropertyMetadata(0));
        public static readonly DependencyProperty PositionProperty = DependencyProperty.Register("Position", typeof(AxisPosition), typeof(Axis), new PropertyMetadata(AxisPosition.Near, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty RadarLabelVisibilityProperty = DependencyProperty.Register("RadarLabelVisibility", typeof(RadarLabelVisibility), typeof(Axis), new PropertyMetadata(RadarLabelVisibility.First, new PropertyChangedCallback(Axis.OnRadarLabelVisibilityChanged)));
        public static readonly DependencyProperty RadarPointIndicesProperty = DependencyProperty.Register("RadarPointIndices", typeof(IList<int>), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnRadarPointIndicesChanged)));
        public static readonly DependencyProperty ReversedProperty = DependencyProperty.Register("Reversed", typeof(bool), typeof(Axis), new PropertyMetadata(false, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register("Scale", typeof(double), typeof(Axis), new PropertyMetadata(1.0, new PropertyChangedCallback(Axis.OnScaleChanged)));
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(object), typeof(Axis), new PropertyMetadata(null, new PropertyChangedCallback(Axis.OnDPChanged)));
        public static readonly DependencyProperty UseExactLimitsProperty = DependencyProperty.Register("UseExactLimits", typeof(bool), typeof(Axis), new PropertyMetadata(false));
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(Axis), new PropertyMetadata(0.0, new PropertyChangedCallback(Axis.OnValueChanged)));
        public static readonly DependencyProperty VisibleProperty = DependencyProperty.Register("Visible", typeof(bool), typeof(Axis), new PropertyMetadata(true, new PropertyChangedCallback(Axis.OnDPChanged)));

        // Events
        public event AnnoCreatedEventHandler AnnoCreated;
        internal event PropertyChangedEventHandler PropertyChanged;
        event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
        {
            add
            {
                this.PropertyChanged += value;
            }
            remove
            {
                this.PropertyChanged -= value;
            }
        }

        // Methods
        public Axis()
            : this(AxisType.Y)
        {
        }

        internal Axis(AxisType atype)
            : base(null)
        {
            //this._axType = AxisType.Y;
            this._minScale = 1E-05;
            this.Change = 0.5;
            this._isTime = null;
            this.IsValidFmt = true;
            this.IsValidTimeFmt = true;
            this.notify = true;
            this._tmpValue = double.NaN;
            this._tmpScale = double.NaN;
            base._axis = this;
            this.iax = this;
            this._axType = atype;
        }

        private void _timer_Tick(object sender, EventArgs e)
        {
            this._timer.Stop();
            if ((this._tmpValue != this.Value) || (this._tmpScale != this.Scale))
            {
                this.notify = false;
                this.Value = this._tmpValue;
                this.Scale = this._tmpScale;
                this.notify = true;
                this.OnPropertyChanged("");
            }
        }

        internal void FireAnnoCreated(AnnoCreatedEventArgs args)
        {
            if (this.AnnoCreated != null)
            {
                this.AnnoCreated(this, args);
            }
        }

        internal string Format(object val)
        {
            return this.iax.Format(val);
        }

        public Rect GetAxisRect()
        {
            return ((AxisCanvas)this.iax).AxisRect;
        }

        internal bool IsTimeInternal(Chart chart)
        {
            if (this._isTime.HasValue)
            {
                return this._isTime.Value;
            }
            if (base.ReadLocalValue(IsTimeProperty) != DependencyProperty.UnsetValue)
            {
                return this.IsTime;
            }
            if (((this.AxisType != AxisType.X) || (chart == null)) || (((chart.ChartType != ChartType.Candle) && (chart.ChartType != ChartType.HighLowOpenClose)) && (chart.ChartType != ChartType.Gantt)))
            {
                return false;
            }
            return true;
        }

        private static void OnAnnoFormatChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            Axis axis = (Axis)obj;
            axis.IsValidFmt = TestFormat(axis.AnnoFormat, false);
            axis.IsValidTimeFmt = TestFormat(axis.AnnoFormat, true);
            axis.OnPropertyChanged(args.Property.ToString());
        }

        private static void OnAutoMaxChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            Axis axis = (Axis)obj;
            if ((bool)args.NewValue)
            {
                if (axis.notify)
                {
                    axis.notify = false;
                    axis.Max = double.NaN;
                    axis.notify = true;
                }
                else
                {
                    axis.Max = double.NaN;
                }
            }
            axis.OnPropertyChanged("AutoMax");
        }

        private static void OnAutoMinChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            Axis axis = (Axis)obj;
            if ((bool)args.NewValue)
            {
                if (axis.notify)
                {
                    axis.notify = false;
                    axis.Min = double.NaN;
                    axis.notify = true;
                }
                else
                {
                    axis.Min = double.NaN;
                }
            }
            axis.OnPropertyChanged("AutoMin");
        }

        private static void OnDPChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((Axis)obj).OnPropertyChanged(args.Property.ToString());
        }

        private static void OnIsTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            Axis axis = (Axis)obj;
            axis._isTime = new bool?((bool)e.NewValue);
            axis.IsValidFmt = TestFormat(axis.AnnoFormat, false);
            axis.IsValidTimeFmt = TestFormat(axis.AnnoFormat, true);
            axis.OnPropertyChanged("IsTime");
        }

        private static void OnLogBaseChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            Axis axis = (Axis)obj;
            if (((axis.LogBase <= 0.0) || (axis.LogBase > 3.4028234663852886E+38)) || (axis.LogBase == 1.0))
            {
                axis.LogBase = double.NaN;
            }
            else
            {
                axis.OnPropertyChanged("LogBase");
            }
        }

        private static void OnMaxChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            Axis axis = (Axis)obj;
            if (axis.notify)
            {
                axis.notify = false;
                axis.AutoMax = double.IsNaN(axis.Max);
                axis.notify = true;
            }
            else
            {
                axis.AutoMax = double.IsNaN(axis.Max);
            }
            axis.OnPropertyChanged("Max");
        }

        private static void OnMinChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            Axis axis = (Axis)obj;
            if (axis.notify)
            {
                axis.notify = false;
                axis.AutoMin = double.IsNaN(axis.Min);
                axis.notify = true;
            }
            else
            {
                axis.AutoMin = double.IsNaN(axis.Min);
            }
            axis.OnPropertyChanged("Min");
        }

        private void OnPropertyChanged(string name)
        {
            if (this.notify && (this.PropertyChanged != null))
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        private static void OnRadarLabelVisibilityChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((Axis)obj).OnPropertyChanged("RadarLabelVisibility");
        }

        private static void OnRadarPointIndicesChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((Axis)obj).OnPropertyChanged("RadarPointIndices");
        }

        private static void OnScaleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            Axis axis = (Axis)obj;
            if (axis.Scale < axis.MinScale)
            {
                axis.Scale = axis.MinScale;
            }
            else if (axis.Scale > 1.0)
            {
                axis.Scale = 1.0;
            }
            else
            {
                axis.OnPropertyChanged("Scale");
            }
        }

        private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            Axis axis = (Axis)obj;
            if (axis.Value > 1.0)
            {
                axis.Value = 1.0;
            }
            else if (axis.Value < 0.0)
            {
                axis.Value = 0.0;
            }
            else if (double.IsNaN(axis.Value))
            {
                axis.Value = 0.0;
            }
            axis.OnPropertyChanged("Value");
        }

        public Point PointFromData(Point pt)
        {
            if ((base.Chart == null) || (base.Chart.View == null))
            {
                return new Point(double.NaN, double.NaN);
            }
            Point point = base.Chart.View.PointFromData(pt);
            if (this.iax != null)
            {
                if (this.AxisType == AxisType.X)
                {
                    point.X = this.iax.FromData(pt.X);
                    return point;
                }
                if (this.AxisType == AxisType.Y)
                {
                    point.Y = this.iax.FromData(pt.Y);
                }
            }
            return point;
        }

        public Point PointToData(Point pt)
        {
            if ((base.Chart == null) || (base.Chart.View == null))
            {
                return new Point(double.NaN, double.NaN);
            }
            Point point = base.Chart.View.PointToData(pt);
            if (this.iax != null)
            {
                if (this.AxisType == AxisType.X)
                {
                    point.X = this.iax.ToData(pt.X);
                    return point;
                }
                if (this.AxisType == AxisType.Y)
                {
                    point.Y = this.iax.ToData(pt.Y);
                }
            }
            return point;
        }

        internal void Reset()
        {
            this.AnnoAngle = 0.0;
            this.AnnoFormat = "";
            this.AnnoPosition = AnnoPosition.Auto;
            this.AnnoTemplate = null;
            this.ItemsSource = null;
            this.MajorUnit = double.NaN;
            this.MajorTickThickness = 1.0;
            this.MajorTickHeight = 2.0;
            this.MajorTickOverlap = 0.0;
            if (this._fixedType)
            {
                this.SetFixedType(this.AxisType);
            }
            else
            {
                this.MajorGridStroke = null;
                this.MajorGridStrokeDashes = null;
            }
            this.AutoMin = true;
            this.AutoMax = true;
            this.Min = double.NaN;
            this.Max = double.NaN;
            this.MinorGridStroke = null;
            this.MinorGridStrokeDashes = null;
            this.MinorGridStrokeThickness = 0.0;
            this.MinorTickThickness = 1.0;
            this.MinorTickHeight = 1.0;
            this.MinorTickOverlap = 0.0;
            this.MinorUnit = double.NaN;
            this.MinScale = 1E-05;
            this.Position = AxisPosition.Near;
            this.Reversed = false;
            this.Scale = 1.0;
            this.Value = 0.0;
            this.Origin = double.NaN;
            this.LogBase = double.NaN;
            this.Title = null;
            base.ClearValue(IsTimeProperty);
            this._isTime = null;
            this.MajorGridStrokeThickness = 0.5;
            this.MinorGridStrokeThickness = 0.25;
        }

        private void ScrollBar_AxisRangeChanged(object sender, AxisRangeChangedEventArgs e)
        {
            this._tmpValue = e.Value;
            this._tmpScale = e.Scale;
            if (((this._tmpValue != this.Value) || (this._tmpScale != this.Scale)) && !this.Timer.IsEnabled)
            {
                if (base.Chart != null)
                {
                    this.Timer.Interval = TimeSpan.FromMilliseconds(base.Chart.ActionUpdateDelay);
                }
                this.Timer.Start();
            }
        }

        internal void SetAxisLine(Line line)
        {
            if (this.notify)
            {
                this.notify = false;
                this.AxisLine = line;
                this.notify = true;
            }
            else
            {
                this.AxisLine = line;
            }
        }

        internal void SetFixedType(AxisType type)
        {
            this._axType = type;
            this._fixedType = true;
            if (this.MajorGridStrokeThickness == 0.0)
            {
                this.MajorGridStrokeThickness = 0.5;
            }
            if (this.MajorGridStroke == null)
            {
                this.MajorGridStroke = new SolidColorBrush(Colors.DarkGray);
            }
        }

        private static bool TestFormat(string fmt, bool time)
        {
            try
            {
                if (!string.IsNullOrEmpty(fmt))
                {
                    if (time)
                    {
                        DateTime.Now.ToString(fmt, CultureInfo.CurrentCulture);
                    }
                    else
                    {
                        0.0.ToString(fmt, CultureInfo.CurrentCulture);
                    }
                }
                return true;
            }
            catch (FormatException)
            {
                return false;
            }
        }

        // Properties
        public double ActualMax
        {
            get
            {
                return this._actualMax;
            }
            internal set
            {
                if (!double.IsNaN(value))
                {
                    this._actualMax = value;
                }
            }
        }

        public double ActualMin
        {
            get
            {
                return this._actualMin;
            }
            internal set
            {
                if (!double.IsNaN(value))
                {
                    this._actualMin = value;
                }
            }
        }

        public double AnnoAngle
        {
            get
            {
                return (double)base.GetValue(AnnoAngleProperty);
            }
            set
            {
                base.SetValue(AnnoAngleProperty, value);
            }
        }

        public string AnnoFormat
        {
            get
            {
                return (string)base.GetValue(AnnoFormatProperty);
            }
            set
            {
                base.SetValue(AnnoFormatProperty, value);
            }
        }

        internal string AnnoFormatInternal { get; set; }

        public AnnoPosition AnnoPosition
        {
            get
            {
                return (AnnoPosition)base.GetValue(AnnoPositionProperty);
            }
            set
            {
                base.SetValue(AnnoPositionProperty, value);
            }
        }

        public object AnnoTemplate
        {
            get
            {
                return base.GetValue(AnnoTemplateProperty);
            }
            set
            {
                base.SetValue(AnnoTemplateProperty, value);
            }
        }

        public AnnoVisibility AnnoVisibility
        {
            get
            {
                return (AnnoVisibility)base.GetValue(AnnoVisibilityProperty);
            }
            set
            {
                base.SetValue(AnnoVisibilityProperty, value);
            }
        }

        public bool AutoMax
        {
            get
            {
                return (bool)base.GetValue(AutoMaxProperty);
            }
            set
            {
                base.SetValue(AutoMaxProperty, value);
            }
        }

        public bool AutoMin
        {
            get
            {
                return (bool)base.GetValue(AutoMinProperty);
            }
            set
            {
                base.SetValue(AutoMinProperty, value);
            }
        }

        public Line AxisLine
        {
            get
            {
                return (Line)base.GetValue(AxisLineProperty);
            }
            set
            {
                base.SetValue(AxisLineProperty, value);
            }
        }

        public AxisType AxisType
        {
            get
            {
                return this._axType;
            }
            set
            {
                if ((this._axType != value) && !this._fixedType)
                {
                    this._axType = value;
                    this.OnPropertyChanged("AxisType");
                }
            }
        }

        public Func<double, double> DependentAxisConverter
        {
            get
            {
                return this._dependentConverter;
            }
            set
            {
                this._dependentConverter = value;
            }
        }

        public FontFamily FontFamily
        {
            get
            {
                return (FontFamily)base.GetValue(FontFamilyProperty);
            }
            set
            {
                base.SetValue(FontFamilyProperty, value);
            }
        }

        public double FontSize
        {
            get
            {
                return (double)base.GetValue(FontSizeProperty);
            }
            set
            {
                base.SetValue(FontSizeProperty, value);
            }
        }

        public FontStretch FontStretch
        {
            get
            {
                return (FontStretch)base.GetValue(FontStretchProperty);
            }
            set
            {
                base.SetValue(FontStretchProperty, value);
            }
        }

        public FontStyle FontStyle
        {
            get
            {
                return (FontStyle)base.GetValue(FontStyleProperty);
            }
            set
            {
                base.SetValue(FontStyleProperty, value);
            }
        }

        public FontWeight FontWeight
        {
            get
            {
                return (FontWeight)base.GetValue(FontWeightProperty);
            }
            set
            {
                base.SetValue(FontWeightProperty, value);
            }
        }

        public Brush Foreground
        {
            get
            {
                return (Brush)base.GetValue(ForegroundProperty);
            }
            set
            {
                base.SetValue(ForegroundProperty, value);
            }
        }

        internal Brush ForegroundInternal
        {
            get
            {
                Brush foreground = this.Foreground;
                if (((foreground == null) && (base.Chart != null)) && (base.Chart.Foreground != null))
                {
                    return base.Chart.Foreground;
                }
                return foreground;
            }
        }

        public bool IsDependent
        {
            get
            {
                if (this._fixedType)
                {
                    return false;
                }
                return this._isDependent;
            }
            set
            {
                this._isDependent = value;
            }
        }

        public bool IsTime
        {
            get
            {
                return (bool)base.GetValue(IsTimeProperty);
            }
            set
            {
                base.SetValue(IsTimeProperty, value);
            }
        }

        public Binding ItemsLabelBinding
        {
            get
            {
                return (Binding)base.GetValue(ItemsLabelBindingProperty);
            }
            set
            {
                base.SetValue(ItemsLabelBindingProperty, value);
            }
        }

        public IEnumerable ItemsSource
        {
            get
            {
                return (IEnumerable)base.GetValue(ItemsSourceProperty);
            }
            set
            {
                base.SetValue(ItemsSourceProperty, value);
            }
        }

        public Binding ItemsValueBinding
        {
            get
            {
                return (Binding)base.GetValue(ItemsValueBindingProperty);
            }
            set
            {
                base.SetValue(ItemsValueBindingProperty, value);
            }
        }

        public double LogBase
        {
            get
            {
                return (double)base.GetValue(LogBaseProperty);
            }
            set
            {
                base.SetValue(LogBaseProperty, value);
            }
        }

        public Brush MajorGridFill
        {
            get
            {
                return (Brush)base.GetValue(MajorGridFillProperty);
            }
            set
            {
                base.SetValue(MajorGridFillProperty, value);
            }
        }

        public Brush MajorGridStroke
        {
            get
            {
                return (Brush)base.GetValue(MajorGridStrokeProperty);
            }
            set
            {
                base.SetValue(MajorGridStrokeProperty, value);
            }
        }

        public DoubleCollection MajorGridStrokeDashes
        {
            get
            {
                return (DoubleCollection)base.GetValue(MajorGridStrokeDashesProperty);
            }
            set
            {
                base.SetValue(MajorGridStrokeDashesProperty, value);
            }
        }

        public double MajorGridStrokeThickness
        {
            get
            {
                return (double)base.GetValue(MajorGridStrokeThicknessProperty);
            }
            set
            {
                base.SetValue(MajorGridStrokeThicknessProperty, value);
            }
        }

        public double MajorTickHeight
        {
            get
            {
                return (double)base.GetValue(MajorTickHeightProperty);
            }
            set
            {
                base.SetValue(MajorTickHeightProperty, value);
            }
        }

        public double MajorTickOverlap
        {
            get
            {
                return (double)base.GetValue(MajorTickOverlapProperty);
            }
            set
            {
                base.SetValue(MajorTickOverlapProperty, value);
            }
        }

        public Brush MajorTickStroke
        {
            get
            {
                return (Brush)base.GetValue(MajorTickStrokeProperty);
            }
            set
            {
                base.SetValue(MajorTickStrokeProperty, value);
            }
        }

        public double MajorTickThickness
        {
            get
            {
                return (double)base.GetValue(MajorTickThicknessProperty);
            }
            set
            {
                base.SetValue(MajorTickThicknessProperty, value);
            }
        }

        public double MajorUnit
        {
            get
            {
                return (double)base.GetValue(MajorUnitProperty);
            }
            set
            {
                base.SetValue(MajorUnitProperty, value);
            }
        }

        public double Max
        {
            get
            {
                return (double)base.GetValue(MaxProperty);
            }
            set
            {
                base.SetValue(MaxProperty, value);
            }
        }

        public double Min
        {
            get
            {
                return (double)base.GetValue(MinProperty);
            }
            set
            {
                base.SetValue(MinProperty, value);
            }
        }

        public Brush MinorGridStroke
        {
            get
            {
                return (Brush)base.GetValue(MinorGridStrokeProperty);
            }
            set
            {
                base.SetValue(MinorGridStrokeProperty, value);
            }
        }

        public DoubleCollection MinorGridStrokeDashes
        {
            get
            {
                return (DoubleCollection)base.GetValue(MinorGridStrokeDashesProperty);
            }
            set
            {
                base.SetValue(MinorGridStrokeDashesProperty, value);
            }
        }

        public double MinorGridStrokeThickness
        {
            get
            {
                return (double)base.GetValue(MinorGridStrokeThicknessProperty);
            }
            set
            {
                base.SetValue(MinorGridStrokeThicknessProperty, value);
            }
        }

        public double MinorTickHeight
        {
            get
            {
                return (double)base.GetValue(MinorTickHeightProperty);
            }
            set
            {
                base.SetValue(MinorTickHeightProperty, value);
            }
        }

        public double MinorTickOverlap
        {
            get
            {
                return (double)base.GetValue(MinorTickOverlapProperty);
            }
            set
            {
                base.SetValue(MinorTickOverlapProperty, value);
            }
        }

        public Brush MinorTickStroke
        {
            get
            {
                return (Brush)base.GetValue(MinorTickStrokeProperty);
            }
            set
            {
                base.SetValue(MinorTickStrokeProperty, value);
            }
        }

        public double MinorTickThickness
        {
            get
            {
                return (double)base.GetValue(MinorTickThicknessProperty);
            }
            set
            {
                base.SetValue(MinorTickThicknessProperty, value);
            }
        }

        public double MinorUnit
        {
            get
            {
                return (double)base.GetValue(MinorUnitProperty);
            }
            set
            {
                base.SetValue(MinorUnitProperty, value);
            }
        }

        [DefaultValue((double)1E-05)]
        public double MinScale
        {
            get
            {
                return this._minScale;
            }
            set
            {
                if (value > 1.0)
                {
                    value = 1.0;
                }
                else if (value <= 0.0)
                {
                    value = 1E-05;
                }
                if (this._minScale != value)
                {
                    this._minScale = value;
                    if (this.Scale < this._minScale)
                    {
                        this.Scale = this._minScale;
                    }
                    this.OnPropertyChanged("MinScale");
                }
            }
        }

        public double Origin
        {
            get
            {
                return (double)base.GetValue(OriginProperty);
            }
            set
            {
                base.SetValue(OriginProperty, value);
            }
        }

        public int PlotAreaIndex
        {
            get
            {
                return (int)base.GetValue(PlotAreaIndexProperty);
            }
            set
            {
                base.SetValue(PlotAreaIndexProperty, value);
            }
        }

        public AxisPosition Position
        {
            get
            {
                return (AxisPosition)base.GetValue(PositionProperty);
            }
            set
            {
                base.SetValue(PositionProperty, value);
            }
        }

        public RadarLabelVisibility RadarLabelVisibility
        {
            get
            {
                return (RadarLabelVisibility)base.GetValue(RadarLabelVisibilityProperty);
            }
            set
            {
                base.SetValue(RadarLabelVisibilityProperty, value);
            }
        }

        public IList<int> RadarPointIndices
        {
            get
            {
                return (IList<int>)base.GetValue(RadarPointIndicesProperty);
            }
            set
            {
                base.SetValue(RadarPointIndicesProperty, value);
            }
        }

        public bool Reversed
        {
            get
            {
                return (bool)base.GetValue(ReversedProperty);
            }
            set
            {
                base.SetValue(ReversedProperty, value);
            }
        }

        public double Scale
        {
            get
            {
                return (double)base.GetValue(ScaleProperty);
            }
            set
            {
                base.SetValue(ScaleProperty, value);
            }
        }

        public IAxisScrollBar ScrollBar
        {
            get
            {
                return this._asb;
            }
            set
            {
                if (value != this._asb)
                {
                    if (this._asb != null)
                    {
                        this._asb.AxisRangeChanged -= new AxisRangeChangedEventHandler(this.ScrollBar_AxisRangeChanged);
                    }
                    this._asb = value;
                    if (this._asb != null)
                    {
                        this._asb.Axis = this;
                        this._asb.AxisRangeChanged += new AxisRangeChangedEventHandler(this.ScrollBar_AxisRangeChanged);
                    }
                }
            }
        }

        private DispatcherTimer Timer
        {
            get
            {
                if (this._timer == null)
                {
                    DispatcherTimer timer = new DispatcherTimer
                    {
                        Interval = TimeSpan.FromMilliseconds(100.0)
                    };
                    this._timer = timer;
                    this._timer.Tick += new EventHandler(this._timer_Tick);
                }
                return this._timer;
            }
        }

        public object Title
        {
            get
            {
                return base.GetValue(TitleProperty);
            }
            set
            {
                base.SetValue(TitleProperty, value);
            }
        }

        public bool UseExactLimits
        {
            get
            {
                return (bool)base.GetValue(UseExactLimitsProperty);
            }
            set
            {
                base.SetValue(UseExactLimitsProperty, value);
            }
        }

        public double Value
        {
            get
            {
                return (double)base.GetValue(ValueProperty);
            }
            set
            {
                base.SetValue(ValueProperty, value);
            }
        }

        public bool Visible
        {
            get
            {
                return (bool)base.GetValue(VisibleProperty);
            }
            set
            {
                base.SetValue(VisibleProperty, value);
            }
        }
    }
}
